/*
 * Copyright Aristool AG Switzerland
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package org.opprua.tidy.util;

import java.util.Collections;
import java.util.Map;
import java.util.Stack;
import java.util.TreeMap;

/**
 * TODO: add Java doc
 * 
 * Prepared for first commit: 15.07.2007
 * 
 * @author Lin Li
 */
public class SimpleProfiler {

  private static class Tracker {

    long last = 0L;
    Stack<String> stack = new Stack<String>();
    Map<String, Long> map = new TreeMap<String, Long>();
  };

  private static Map<String, Tracker> myScope = Collections
              .synchronizedMap(new TreeMap<String, Tracker>());

  // ** private static long frequency = Perf.getPerf().highResFrequency();

  public static void enter(String name) {
    Stack<String> s = getTracker().stack;
    if (s.size() == 0) {
      s.push("In between");
      replaceLast();
    }
    String last = (String) s.peek();
    update(last);
    s.push(name);
  }

  public static void leave(String name) {
    Stack<String> s = getTracker().stack;

    while (s.size() > 0) {
      String loc = (String) s.pop();
      if (loc.equals(name)) {
        break;
      }

      System.err.println("Failed to pop matching enter for: " + name + "(" + loc + ")");
    }
    if (s.size() == 0) {
      s.push("In between");
    }
    update(name);
  }

  public static void clear() {
    myScope.put(Thread.currentThread().getName(), new Tracker());
    // ** myScope.put(LAST_KEY, new Long(Perf.getPerf().highResCounter()));
  }

  public static void print() {
    Map<String, Long> kept = getTracker().map;

    System.out.println("======== Statistics =========");
    String[] k = (String[]) kept.keySet().toArray(new String[kept.size()]);
    for (int i = 0; i < k.length; i++) {
      System.out.println(k[i] + "    " + (((Long) kept.get(k[i])).longValue() * 1000));
      // ** / frequency);
    }
  }

  private static long replaceLast() {
    long l = getTracker().last;
    long n = l; // ** Perf.getPerf().highResCounter();
    getTracker().last = n;
    return n - l;
  }

  private static void update(String name) {
    Map<String, Long> kept = getTracker().map;
    Long sum = (Long) kept.get(name);
    if (sum == null) {
      sum = new Long(0L);
    }
    long rep = replaceLast();
    sum = new Long(sum.longValue() + rep);
    kept.put(name, sum);
  }

  private static Tracker getTracker() {
    Tracker t = myScope.get(Thread.currentThread().getName());
    if (t == null) {
      t = new Tracker();
      myScope.put(Thread.currentThread().getName(), t);
    }
    return t;
  }
}
